package
{
	import com.adobe.serialization.json.JSON;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.geom.Point;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import flash.net.URLRequestHeader;
	import flash.net.URLRequestMethod;
	import flash.net.URLVariables;
	import flash.utils.Dictionary;
	
	import model.LuckyItem;
	import model.User;
	
	import org.iotashan.oauth.OAuthConsumer;
	import org.iotashan.oauth.OAuthRequest;
	import org.iotashan.oauth.OAuthSignatureMethod_HMAC_SHA1;
	import org.iotashan.oauth.OAuthToken;
	
	public class LuckyClient extends EventDispatcher
	{
		private static const ACCESS_TOKEN_URL:String = "http://localhost:8080/oauth/access_token";
		private static const GET_USER_URL:String = "http://localhost:8080/api/user/queryuser";
		private static const CREAT_ITEM_URL:String = "http://localhost:8080/api/luckyItem/creatItem";
		private static const UPDATE_LOCATION_URL:String = "http://localhost:8080/api/user/updateuserlocation";
		private static const GET_ITEMS_BY_UID_URL:String = "http://localhost:8080/api/luckyItem/getitemsbyuid";
		private static const GET_LOCAL_USERS_URL:String = "http://localhost:8080/api/user/querylocaluser";
		
		private var _oauthRequest:OAuthRequest;
		private var _consumerKey:String;
		private var _consumerSecret:String;
		
		private var _user:User;
		private var _membsers:Dictionary;
		
		[Event(name="loginComplete",type="ClientEvent")]
		[Event(name="loginFailed",type="ClientEvent")]
		public function LuckyClient(consumerKey:String,consumerSecret:String)
		{
			super(null);
			_consumerKey = consumerKey;
			_consumerSecret = consumerSecret;
			_membsers = new Dictionary();
		}
		
		public function get user():User
		{
			return _user;
		}
		
		public function get membsers():Dictionary
		{
			return _membsers;
		}
		
		public function referesh():void
		{
			getLocalUsers(_user.location);
		}
		
		private function request(url:String,params:Object,onComplete:Function,method:String=URLRequestMethod.POST,onError:Function = null):void
		{
			_oauthRequest.requestURL = url;
			var head:URLRequestHeader = _oauthRequest.buildRequest(new OAuthSignatureMethod_HMAC_SHA1(),OAuthRequest.RESULT_TYPE_HEADER);
			var request:URLRequest = new URLRequest(url);
			var loaderVar:URLVariables = new URLVariables();
			for(var param:String in params)
			{
				loaderVar[param] = params[param];
			}
			request.method = method;
			request.requestHeaders.push(head);
			request.data = loaderVar;
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE,onRequestComplete);
			loader.load(request);
			
			function onRequestComplete(evt:Event):void
			{
				loader.removeEventListener(Event.COMPLETE,onRequestComplete);
				try
				{
					trace(String(evt.target.data));
					var data:Object = JSON.decode(String(evt.target.data));
					if(data.result.toLowerCase() != "false")
					{
						onComplete(data);
					}else
					{
						dispatchEvent(new ClientEvent(ClientEvent.LOAD_DATA_FAILED,String(evt.target.data)));
					}
				}catch(e:Error)
				{
					dispatchEvent(new ClientEvent(ClientEvent.DECODE_DATA_FAILED,String(evt.target.data)));
				}
			}
		}
		
		
		public function login(username:String,password:String):void
		{
			_oauthRequest = new OAuthRequest(OAuthRequest.HTTP_MEHTOD_POST,ACCESS_TOKEN_URL,{x_auth_username:username,x_auth_password:password},new OAuthConsumer(_consumerKey,_consumerSecret),null);
			var head:URLRequestHeader = _oauthRequest.buildRequest(new OAuthSignatureMethod_HMAC_SHA1(),OAuthRequest.RESULT_TYPE_HEADER);
			var request:URLRequest = new URLRequest(ACCESS_TOKEN_URL);
			request.requestHeaders.push(head);
			request.method = URLRequestMethod.POST;
			var data:URLVariables = new URLVariables();
			data.username = username;
			data.password = password;
			request.data = data;
			var loader:URLLoader = new URLLoader();
			loader.addEventListener(Event.COMPLETE,onLoginComplete);
			loader.load(request);
		}
		
		private function onLoginComplete(evt:Event):void
		{
			var loader:URLLoader = evt.target as URLLoader;
			loader.removeEventListener(Event.COMPLETE,onLoginComplete);
			try
			{
				var data:Object = JSON.decode(String(evt.target.data));
				if(data.result != "false")
				{
					_user = new User(data.user);
					_membsers[_user.username] = _user;
					var at:OAuthToken = new OAuthToken(data.access_token,data.access_token_secret);
					_oauthRequest.token = at;
					dispatchEvent(new ClientEvent(ClientEvent.LOGIN_COMPLETE,ClientMessage.LOGIN_COMPLETE,data));
				}else
				{
					dispatchEvent(new ClientEvent(ClientEvent.LOGIN_FAILED,data.message));
				}
			}catch(err:Error)
			{
				trace(err.message);
				dispatchEvent(new ClientEvent(ClientEvent.LOGIN_FAILED,String(evt.target.data)));
			}
		}
		
		public function queryUser(uid:String="",username:String=""):void
		{
			if(uid!="")
			{
				request(GET_USER_URL,{uid:uid},onQueryUserComplete);
			}else if(username!="")
			{
				request(GET_USER_URL,{username:username},onQueryUserComplete);
			}
		}
		
		private function onQueryUserComplete(data:Object):void
		{
			dispatchEvent(new ClientEvent(ClientEvent.QUERY_USER_COMPLETE,ClientMessage.QUERY_USER_COMPLETE,String(data)));
		}
		
		public function setLocation(pt:Point):void
		{
			request(UPDATE_LOCATION_URL,{location:pt.x+","+pt.y},onSetLocationComplete);
		}
		
		private function onSetLocationComplete(data:Object):void
		{
			_user.location = new Point(Number(data.location.split(",")[0]),Number(data.location.split(",")[1]));
			dispatchEvent(new ClientEvent(ClientEvent.UPDATE_LOCATION_COMPLETE,ClientMessage.UPDATE_LOCATION_COMPLETE,String(data)));
		}
		
		public function creatItem(content:String):void
		{
			request(CREAT_ITEM_URL,{content:content,longitude:_user.location.x,latitude:_user.location.y},creatItemComplete);
		}
		
		private function creatItemComplete(data:Object):void
		{
			dispatchEvent(new ClientEvent(ClientEvent.CREAT_ITEM_COMPLETE,ClientMessage.CREAT_ITEM_COMPLETE,data));
		}
		
		public function getItemByUid(uid:int,count:int=20,page:int=-1):void
		{
			var data:Object = {uid:uid,count:count};
			if(page != -1) data["page"] = page;
			request(GET_ITEMS_BY_UID_URL,data,onGetItemsComplete);
		}
		
		private function onGetItemsComplete(data:Object):void
		{
			var item:LuckyItem = new LuckyItem(data.items[0]);
			dispatchEvent(new ClientEvent(ClientEvent.GET_ITEM_COMPLETE,ClientMessage.GET_ITEM_COMPLETE,item));
		}
		
		public function getLocalUsers(pt:Point):void
		{
			request(GET_LOCAL_USERS_URL,{location:pt.x+","+pt.y},onGetLocalUsersComplete);
		}
		
		private function onGetLocalUsersComplete(data:Object):void
		{
			for each(var member:Object in data.users)
			{
				var user:User = new User(member);
				if(member.latest_item.id != "")user.addItem(new LuckyItem(member.latest_item));
				addUser(user)
			}
		}
		
		private function addUser(user:User):void
		{
			if(_membsers[user.username] != undefined && _membsers[user.username] != null)
			{
				var u:User = User(_membsers[user.username]);
				u.location = user.location;
				dispatchEvent(new ClientEvent(ClientEvent.UPDATE_USER,"",u));
				return;
			}
			_membsers[user.username] = user;
			dispatchEvent(new ClientEvent(ClientEvent.ADD_USER,"",user));
		}
	}
}